#
# This file is a part of the open-eBackup project.
# This Source Code Form is subject to the terms of the Mozilla Public License, v. 2.0.
# If a copy of the MPL was not distributed with this file, You can obtain one at
# http://mozilla.org/MPL/2.0/.
#
# Copyright (c) [2024] Huawei Technologies Co.,Ltd.
#
# THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
# EITHER EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
# MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
#

from common.common import check_command_injection
from common.const import CopyDataTypeEnum
from common.exception.common_exception import ErrCodeException
from informix import LOGGER
from informix.comm.comm import get_local_uuid, check_path_user
from informix.comm.const import JsonConstant, ErrorCode, InformixInfo, RpcParamKey
from informix.param.parse_params import BaseParam


class InformixParseRestoreParam(BaseParam):
    """
    恢复入参json文件的解析
    """

    def __init__(self, json_params, job_manager):
        super(InformixParseRestoreParam, self).__init__(json_params, job_manager, LOGGER)

    @staticmethod
    def get_node_id(node):
        return node.get(JsonConstant.ID, '')

    @staticmethod
    def get_node_extend_instance_status(node):
        return node.get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.INSTANCE_STATUS, '')

    @staticmethod
    def get_node_instance_name(node):
        return node.get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.LOCALSERVER, '')

    def get_job_repositories(self):
        copys = self.get_copys()
        restore_type = self.get_restore_type()
        if restore_type:
            if len(copys) < 2:
                return ''
            repositories = copys[-2].get(JsonConstant.REPOSITORIES, {})
            return repositories
        return copys[-1].get(JsonConstant.REPOSITORIES, [])

    def get_log_area(self):
        copys = self.get_copys()
        repositories = copys[-1].get(JsonConstant.REPOSITORIES, {})
        return self.get_designated_path_ex(3, repositories)

    def get_log_area_list(self):
        copys = self.get_copys()
        repositories = copys[-1].get(JsonConstant.REPOSITORIES, {})
        return self.get_designated_path_ex_list(3, repositories)

    def get_version(self):
        result = self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.TARGET_OBJECT, {}).get(
            JsonConstant.EXTEND_INFO,
            {}).get(JsonConstant.VERSION)
        return result

    def get_copy_version(self):
        copys = self.get_copys()
        if not copys:
            return ''
        nodes = copys[0].get(JsonConstant.PROTECT_ENV, {}).get(JsonConstant.NODES, [])
        if not nodes:
            return ''
        version = nodes[0].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.APPLICATION_VERSION, "")
        return version

    def get_full_copy_id(self):
        copys = self.get_copys()
        for copy in copys:
            if copy.get(JsonConstant.TYPE) == RpcParamKey.FULL_COPY or copy.get(
                    JsonConstant.TYPE) == RpcParamKey.TAPE_ARCHIVE or copy.get(
                    JsonConstant.TYPE) == RpcParamKey.S3_ARCHIVE:
                full_copy_id = copy.get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.COPY_ID, "")
                break
        return full_copy_id

    def get_source_backup_copy_id(self):
        copys = self.get_copys()
        if self.get_restore_type():
            # 时间点恢复
            copy_id = copys[-2].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.COPY_ID, "")
        else:
            # 数据恢复
            latest_data_copy = copys[-1]
            copy_type = latest_data_copy.get("type")
            if copy_type == CopyDataTypeEnum.S3_ARCHIVE or copy_type == CopyDataTypeEnum.TAP_ARCHIVE:
                extend_info = latest_data_copy.get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.EXTEND_INFO, {})
                copy_id = extend_info.get(JsonConstant.COPY_ID, "")
            else:
                copy_id = latest_data_copy.get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.COPY_ID, "")
        if not copy_id:
            raise KeyError()
        return copy_id

    def get_last_copy_id(self):
        copys = self.get_copys()
        if self.get_restore_type():
            copy_id = copys[-2].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.COPY_ID, "")
        else:
            copy_id = copys[-1].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.COPY_ID, "")
        return copy_id

    def get_log_copyid(self):
        copys = self.get_copys()
        copy_id = ''
        if self.get_restore_type():
            copy_id = copys[-1].get(JsonConstant.ID)
        return copy_id

    def get_copys(self):
        copys = self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.COPIES, [])
        if not copys:
            raise KeyError()
        return copys

    def get_target_location(self):
        result = self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.EXTEND_INFO,
                                                                {}).get(JsonConstant.TARGET_LOCATION)
        if not result:
            raise KeyError()
        return result

    def get_base_backupset(self):
        copys = self.get_copys()
        base_backupset = copys[-1].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.BASE_BACKUPSET, [])
        if self.get_restore_type():
            if len(copys) < 2:
                return ''
            base_backupset = copys[-2].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.BASE_BACKUPSET, [])
        return base_backupset

    def get_targetenv_nodes(self):
        result = self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.TARGET_ENV,
                                                                {}).get(JsonConstant.NODES, [])
        if not result:
            raise KeyError()
        return result

    def get_instance_type(self):
        return self.get_curr_info(JsonConstant.INSTANCE_STATUS)

    def get_servernum(self):
        servernum = self.get_curr_info(JsonConstant.SERVER_NUM)
        if servernum and check_command_injection(servernum):
            LOGGER.error("Failed to verify the parameter(servernum) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return servernum

    def old_server_name(self):
        copys = self.get_copys()
        return copys[-1].get(JsonConstant.PROTECT_OBJECT, {}).get(JsonConstant.EXTEND_INFO, {}).get(
            JsonConstant.SERVERNUM)

    def get_curr_info(self, key):
        local_uuid = get_local_uuid()
        nodes = self.get_targetenv_nodes()
        for node in nodes:
            node_id = node.get(JsonConstant.ID)
            if node_id != local_uuid:
                continue
            return node.get(JsonConstant.EXTEND_INFO, {}).get(key)
        raise KeyError()

    def get_onconfig_path_curr(self, db_user=InformixInfo.INFORMIX_USER):
        onconfig_path = self.get_curr_info(JsonConstant.ONCONFIG_PATH)
        if onconfig_path:
            if check_command_injection(onconfig_path) or not check_path_user(onconfig_path, db_user, db_user):
                LOGGER.error("Failed to verify the parameter(onconfig_path_curr) validity.")
                raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return onconfig_path

    def get_onconfig_name_curr(self, db_user=InformixInfo.INFORMIX_USER):
        onconfig_path = self.get_onconfig_path_curr(db_user)
        name = onconfig_path.rsplit('/', 1)[-1]
        if not name:
            raise KeyError()
        if name and check_command_injection(name):
            LOGGER.error("Failed to verify the parameter(name) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return name

    def get_sqlhosts_path_curr(self, db_user=InformixInfo.INFORMIX_USER):
        sqlhosts_path = self.get_curr_info(JsonConstant.SQLHOSTS_PATH)
        if sqlhosts_path:
            if check_command_injection(sqlhosts_path) or not check_path_user(sqlhosts_path, db_user, db_user):
                LOGGER.error("Failed to verify the parameter(sqlhosts_path_curr) validity.")
                raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return sqlhosts_path

    def get_rootdbs_path_curr(self):
        return self.get_curr_info(JsonConstant.ROOTDBS_PATH)

    def get_instance_name_curr(self):
        instance_name_curr = self.get_curr_info(JsonConstant.LOCALSERVER)
        if instance_name_curr and check_command_injection(instance_name_curr):
            LOGGER.error("Failed to verify the parameter(instance_name_curr) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return instance_name_curr

    def get_arch_copy_id(self):
        copys = self.get_copys()
        if not copys:
            return ''
        copy_id = copys[0].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.EXTEND_INFO, {}).get(
            JsonConstant.COPY_ID)
        if copy_id and check_command_injection(copy_id):
            LOGGER.error("Failed to verify the parameter(copy_id) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return copy_id

    def get_restore_type(self):
        result = self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.EXTEND_INFO, {}).get(
            JsonConstant.RESTORE_TIMESTAMP)
        return result

    def get_copy_instance_name(self):
        copys = self.get_copys()
        copy_instance_name = copys[-1].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.INSTANCE_NAME, '')
        LOGGER.info(f"First copy {copy_instance_name}")
        if self.get_restore_type():
            LOGGER.info(f"Enter info")
            if len(copys) < 2:
                LOGGER.info(f"Get Second")
                return ''
            copy_instance_name = copys[-2].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.INSTANCE_NAME, '')
        LOGGER.info(f"Real Copy {copy_instance_name}")
        if copy_instance_name and check_command_injection(copy_instance_name):
            LOGGER.error("Failed to verify the parameter(copy_instance_name) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return copy_instance_name

    def get_copy_server_num(self):
        copys = self.get_copys()
        copy_instance_name = copys[-1].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.SERVERNUM, '')
        if self.get_restore_type():
            if len(copys) < 2:
                return ''
            copy_instance_name = copys[-2].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.SERVERNUM, '')
        if copy_instance_name and check_command_injection(copy_instance_name):
            LOGGER.error("Failed to verify the parameter(copy_instance_name) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return copy_instance_name

    def get_arch_copy_instance_name(self):
        copys = self.get_copys()
        if not copys:
            return ''
        copy_instance_name = copys[0].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.EXTEND_INFO, {}).get(
            JsonConstant.INSTANCE_NAME, '')
        if copy_instance_name and check_command_injection(copy_instance_name):
            LOGGER.error("Failed to verify the parameter(copy_instance_name) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return copy_instance_name

    def get_arch_copy_server_num(self):
        copys = self.get_copys()
        if not copys:
            return ''
        copy_instance_name = copys[0].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.EXTEND_INFO, {}).get(
            JsonConstant.SERVERNUM, '')
        if copy_instance_name and check_command_injection(copy_instance_name):
            LOGGER.error("Failed to verify the parameter(copy_instance_name) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return copy_instance_name

    def get_copy_root_dbs(self):
        copys = self.get_copys()
        if not copys:
            return ''
        rootdbs_path = copys[0].get(JsonConstant.EXTEND_INFO, {}).get(JsonConstant.EXTEND_INFO, {}).get(
            JsonConstant.ROOTDBS_PATH, '')
        if rootdbs_path:
            return rootdbs_path
        rootdbs_path = copys[0].get(JsonConstant.EXTEND_INFO, {}).get(
            JsonConstant.ROOTDBS_PATH, '')
        return rootdbs_path

    def get_old_instance_name(self):
        copys = self.get_copys()
        old_instance_name = copys[-1].get(JsonConstant.PROTECT_OBJECT, {}).get(JsonConstant.EXTEND_INFO, {}).get(
            JsonConstant.LOCALSERVER)
        if old_instance_name and check_command_injection(old_instance_name):
            LOGGER.error("Failed to verify the parameter(old_instance_name) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return old_instance_name

    def get_resoruce_type(self):
        resource_type = self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.TARGET_OBJECT, {}).get(
            JsonConstant.SUB_TYPE)
        return resource_type

    def get_local_log_backup_path(self):
        """
        获取本地日志备份路径
        :return:
        """
        log_backup_path = self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.TARGET_ENV, {}).get(
            JsonConstant.EXTEND_INFO, {}).get(JsonConstant.LOG_BACKUP_PATH, '')
        if log_backup_path and check_command_injection(log_backup_path):
            LOGGER.error("Failed to verify the parameter(log_backup_path) validity.")
            raise ErrCodeException(ErrorCode.ERROR_PARAM.value)
        return log_backup_path

    def get_peer_instance_name(self):
        """
        获取集群实例对端节点信息
        :return:
        """
        return self.get_curr_info(JsonConstant.PAIREDSERVER)

    def get_resource_id(self):
        return self._json_param.get(JsonConstant.JOB, {}).get(JsonConstant.TARGET_OBJECT, {}).get(JsonConstant.ID, '')
